package com.yanzhu.api;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.yanzhu.bean.ResponseBean;
import com.yanzhu.constant.Constant;
import com.yanzhu.service.RechargeService;
import com.yanzhu.service.model.PayInfo;
import com.yanzhu.service.model.Recharge;
import com.yanzhu.util.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * @Author: 方炎柱
 * @Description: 支付模块
 * @Date: Created in 22:06 2018/1/17
 * @Modified:
 */
@AllArgsConstructor
@RestController
public class PayAPI {

    private static org.slf4j.Logger logger = LoggerFactory.getLogger(PayAPI.class);

    private RechargeService rechargeService;

    //充值
    @RequestMapping(value = "/userRecharge", produces = "text/html;charset=UTF-8")
    public ResponseBean prePay( HttpServletRequest request) {
        String info;

        String uid = request.getParameter("uid");
        String code = request.getParameter("code");
        String recharge_fee = request.getParameter("recharge_fee");

        if(uid == null || uid.equals(""))
            return ResponseBean.fail("缺少用户ID参数！");

        if(code == null || code.equals(""))
            return ResponseBean.fail("缺少code参数！");

        if(recharge_fee == null || recharge_fee.equals(""))
            return ResponseBean.fail("缺少充值金额参数！");

        logger.error("code: " + code);

        String openId = getOpenId(code);
        if(StringUtils.isBlank(openId)) {
            info = "获取到openId为空";
            return ResponseBean.fail(info);
        } else {
            openId = openId.replace("\"", "").trim();

            String clientIP = CommonUtil.getClientIp(request);

            logger.error("openId: " + openId + ", clientIP: " + clientIP);

            String randomNonceStr = RandomUtils.generateMixString(32);
            String prepayId = unifiedOrder(openId, clientIP, randomNonceStr, Float.parseFloat(recharge_fee));

            logger.error("preprayId: " + prepayId);

            if(StringUtils.isBlank(prepayId)) {
                info = "出错了，未获取到prepayId";
                return ResponseBean.fail(info);
            } else {
                Recharge recharge = new Recharge();
                recharge.setUid(Integer.parseInt(uid));
                recharge.setRecharge_fee(Float.parseFloat(recharge_fee));
                recharge.setRecharge_time((int)(new Date().getTime()/1000));
                rechargeService.insert(recharge);
                return ResponseBean.ok("充值成功！");
            }
        }
    }


    private String getOpenId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Constant.APP_ID +
                "&secret=" + Constant.APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";

        HttpUtil httpUtil = new HttpUtil();
        try {

            HttpResult httpResult = httpUtil.doGet(url, null, null);

            if(httpResult.getStatusCode() == 200) {

//                JsonParser jsonParser = new JsonParser();
//                JsonObject obj = (JsonObject) jsonParser.parse(httpResult.getBody());
                JSONObject jsonObject = JSONObject.parseObject(httpResult.getBody());
                logger.info("getOpenId: " + jsonObject.toString());

                if(jsonObject.getString("errcode") != null) {
                    logger.error("getOpenId returns errcode: " + jsonObject.getString("errcode"));
                    return "";
                } else {
                    return jsonObject.getString("openid").toString();
                }
                //return httpResult.getBody();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 调用统一下单接口
     * @param openId
     */
    private String unifiedOrder(String openId, String clientIP, String randomNonceStr, float recharge_fee) {

        try {

            String url = Constant.URL_UNIFIED_ORDER;

            PayInfo payInfo = createPayInfo(openId, clientIP, randomNonceStr, recharge_fee);
            String md5 = getSign(payInfo);
            payInfo.setSign(md5);

            logger.info("md5 value: " + md5);

            String xml = CommonUtil.payInfoToXML(payInfo);
            xml = xml.replace("__", "_").replace("<![CDATA[1]]>", "1");
            //xml = xml.replace("__", "_").replace("<![CDATA[", "").replace("]]>", "");
            logger.info(xml);

            StringBuffer buffer = HttpUtil.httpsRequest(url, "POST", xml);
            logger.info("unifiedOrder request return body: \n" + buffer.toString());
            Map<String, String> result = CommonUtil.parseXml(buffer.toString());


            String return_code = result.get("return_code");
            if(StringUtils.isNotBlank(return_code) && return_code.equals("SUCCESS")) {

                String return_msg = result.get("return_msg");
                if(StringUtils.isNotBlank(return_msg) && !return_msg.equals("OK")) {
                    //log.error("统一下单错误！");
                    return "";
                }

                String prepay_Id = result.get("prepay_id");
                return prepay_Id;

            } else {
                return "";
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    private PayInfo createPayInfo(String openId, String clientIP, String randomNonceStr, float recharge_fee) {

        Date date = new Date();
        String timeStart = TimeUtils.getFormatTime(date, Constant.TIME_FORMAT);
        String timeExpire = TimeUtils.getFormatTime(TimeUtils.addDay(date, Constant.TIME_EXPIRE), Constant.TIME_FORMAT);

        String randomOrderId = CommonUtil.getRandomOrderId();

        PayInfo payInfo = new PayInfo();
        payInfo.setAppid(Constant.APP_ID);
        payInfo.setMch_id(Constant.MCH_ID);
        payInfo.setDevice_info("WEB");
        payInfo.setNonce_str(randomNonceStr);
        payInfo.setSign_type("MD5");  //默认即为MD5
        payInfo.setBody("JSAPI支付测试");
        payInfo.setAttach("支付测试4luluteam");
        payInfo.setOut_trade_no(randomOrderId);
        payInfo.setTotal_fee(recharge_fee);
        payInfo.setSpbill_create_ip(clientIP);
        payInfo.setTime_start(timeStart);
        payInfo.setTime_expire(timeExpire);
        payInfo.setNotify_url(Constant.URL_NOTIFY);
        payInfo.setTrade_type("JSAPI");
        payInfo.setLimit_pay("no_credit");
        payInfo.setOpenid(openId);

        return payInfo;
    }

    private String getSign(PayInfo payInfo) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append("appid=" + payInfo.getAppid())
                .append("&attach=" + payInfo.getAttach())
                .append("&body=" + payInfo.getBody())
                .append("&device_info=" + payInfo.getDevice_info())
                .append("&limit_pay=" + payInfo.getLimit_pay())
                .append("&mch_id=" + payInfo.getMch_id())
                .append("&nonce_str=" + payInfo.getNonce_str())
                .append("&notify_url=" + payInfo.getNotify_url())
                .append("&openid=" + payInfo.getOpenid())
                .append("&out_trade_no=" + payInfo.getOut_trade_no())
                .append("&sign_type=" + payInfo.getSign_type())
                .append("&spbill_create_ip=" + payInfo.getSpbill_create_ip())
                .append("&time_expire=" + payInfo.getTime_expire())
                .append("&time_start=" + payInfo.getTime_start())
                .append("&total_fee=" + payInfo.getTotal_fee())
                .append("&trade_type=" + payInfo.getTrade_type())
                .append("&key=" + Constant.APP_KEY);

        logger.info("排序后的拼接参数：" + sb.toString());

        return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
    }



}


